home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / CPP / METAKIT.ZIP / EXAMPLES / STRUCT / STRUCT.CPP next >
Encoding:
C/C++ Source or Header  |  1996-12-09  |  8.9 KB  |  363 lines

  1. //  struct.cpp  -  data structure display application sample code
  2. //
  3. //  This is a part of the MetaKit library.
  4. //  Copyright (c) 1996 Meta Four Software.
  5. //  All rights reserved.
  6. /////////////////////////////////////////////////////////////////////////////
  7. //
  8. //  This command-line utility displays the data structure of a datafile
  9. //  created with the MetaKit library: as a one-line description (-d), as
  10. //  a terse description without property names (-t), as a graph tree of
  11. //  columns (-c, advanced option), or as a graph tree of fields (default).
  12. //
  13. /////////////////////////////////////////////////////////////////////////////
  14.  
  15. #include "m4kit.h"
  16. #include "k4field.h"
  17. #include "k4table.h"
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. #if defined (macintosh)
  23.     #include /**/ <console.h>
  24.     #define d4_InitMain(c,v)    c = ccommand(&v)
  25. #endif
  26.  
  27. #ifdef _MFC_VER
  28.     #define c4_WordArray        CWordArray
  29. #endif
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32. // This class generates a string with a pretty tree structure map.
  33.  
  34. class CStructureMap
  35. {
  36. public:
  37.     CStructureMap ();
  38.     
  39.     bool AddNode(int level_, const char* name_,
  40.                     int first_ =0, int count_ =0, char enhance_ =0);
  41.     
  42.     const c4_String& Result() const { return _result; }
  43.     
  44. private:
  45.     c4_WordArray _nextVec;
  46.     c4_WordArray _limitVec;
  47.     c4_String _result;
  48. };
  49.  
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CStructureMap
  52.  
  53. CStructureMap::CStructureMap ()
  54. {
  55. }
  56.  
  57.     //@todo does not yet work if repeating/compound field has depth > 0
  58.     
  59. bool CStructureMap::AddNode(int level_, const char* name_,
  60.                                 int first_, int count_, char enhance_)
  61. {
  62.     int n = _nextVec.GetSize();
  63.     if (level_ >= n)
  64.     {
  65.         _nextVec.Add((unsigned short) first_);
  66.         _limitVec.Add((unsigned short) (first_ + count_));
  67.         ++n;
  68.     }
  69.         
  70.     c4_String s, t;
  71.  
  72.     for (int i = 0; i < n; ++i)
  73.     {
  74.         bool more = _nextVec.GetAt(i) < _limitVec.GetAt(i);
  75.  
  76.         if (i < n - 1 || (more && (int) _nextVec.GetAt(i) > first_))
  77.         {
  78.             if (i == level_ - 1)
  79.             {
  80.                 int v = (int) _nextVec.ElementAt(i)++;
  81.                     // this uses a silly int to string conversion ...
  82.                 s += c4_String (v < 10 ? ' ' : '0' + v / 10)
  83.                     + c4_String ('0' + v % 10) + "+-";
  84.             }
  85.             else
  86.                 s += i < level_ - 1 ? more ? "  | " : "    "
  87.                                     : more ? "--|-" : "----";
  88.         }
  89.         
  90.         t += _nextVec.GetAt(i) < _limitVec.GetAt(i) ? "  | " : "    ";
  91.     } 
  92.     
  93.     _result += ((s + " ") + name_) + "\n";
  94.     
  95.     if (enhance_)
  96.     {
  97.         s = t.Left(t.GetLength() - 4) + " ";
  98.         
  99.         int i = strlen(name_);
  100.         if (i < 2)
  101.             i = 2;      
  102.             
  103.         while (--i >= 0)
  104.             s += enhance_;
  105.             
  106.         _result += s + "\n";    
  107.     }
  108.     
  109.     _result += t + "\n";
  110.     
  111.     while (n > 0 && _nextVec.GetAt(n-1) >= _limitVec.GetAt(n-1))
  112.         --n;
  113.  
  114.     _nextVec.SetSize(n);
  115.     _limitVec.SetSize(n);
  116.     
  117.     return n > 0;
  118. }                                      
  119.  
  120. /////////////////////////////////////////////////////////////////////////////
  121.  
  122. static c4_String DisplayFieldStructure(const c4_Field& field_)
  123. {
  124.     CStructureMap map;
  125.     
  126.     const c4_Field* f = &field_;
  127.     do
  128.     {
  129.         if (f->NumSubFields() > 0)
  130.         {
  131.             if (f->IsRepeating())
  132.             {
  133.                 map.AddNode(f->Level(), f->Name(), 1, f->NumSubFields() - 1, '=');
  134.                 
  135.                 if (f->NumSubFields() > 1)
  136.                 {
  137.                     f = & f->SubField(1);
  138.                     continue;
  139.                 }
  140.             }
  141.             else
  142.             {
  143.                 map.AddNode(f->Level(), f->Name(), 0, f->NumSubFields(), '-');
  144.                 
  145.                 f = & f->SubField(0);
  146.                 continue;
  147.             }
  148.         }
  149.         else
  150.             map.AddNode(f->Level(), f->Name());
  151.  
  152.         while (!f->IsRoot())
  153.         {
  154.             c4_Field& parent = f->Parent();
  155.                 
  156.             if (f->Index() < parent.NumSubFields() - 1)
  157.             {
  158.                 f = & parent.SubField(f->Index() + 1);
  159.                 break;
  160.             }
  161.                 
  162.             f = & parent;
  163.         }
  164.         
  165.     } while (!f->IsRoot());
  166.     
  167.     return map.Result();
  168. }
  169.  
  170. static c4_String DisplayTableStructure(const c4_Field& field_)
  171. {
  172.     CStructureMap map;
  173.     
  174.     const c4_Field* f = &field_;
  175.     do
  176.     {
  177.         if (f->NumSubFields() > 0)
  178.         {
  179.             if (f->IsRepeating())
  180.             {
  181.                 map.AddNode(f->SubField(0).Degree(), f->Name(),
  182.                                          0, f->NumSubColumns(), '=');
  183.                 if (f->NumSubFields() > 1)
  184.                 {
  185.                     f = & f->SubField(1);
  186.                     continue;
  187.                 }
  188.             }
  189.             else
  190.             {
  191.                 f = & f->SubField(0);
  192.                 continue;
  193.             }
  194.         }
  195.         else if (f->Width() > 0)
  196.             map.AddNode(f->Degree(), f->Name());
  197.  
  198.         while (!f->IsRoot())
  199.         {
  200.             c4_Field& parent = f->Parent();
  201.                 
  202.             if (f->Index() < parent.NumSubFields() - 1)
  203.             {
  204.                 f = & parent.SubField(f->Index() + 1);
  205.                 break;
  206.             }
  207.                 
  208.             f = & parent;
  209.         }
  210.         
  211.     } while (!f->IsRoot());
  212.     
  213.     return map.Result();
  214. }
  215.  
  216. /////////////////////////////////////////////////////////////////////////////
  217.  
  218. #ifdef _DEBUG
  219.  
  220. void TestStructureMap()
  221. {
  222.     static struct c_Info { int level, count; const char* name; } info [] =
  223.     {
  224.         0,  1, "root",
  225.         1,  6, "doc",
  226.         2,  3, "naw",
  227.         3,  2, "n",
  228.         4, -1, "vn",
  229.         2, -1, "x",
  230.         4, -1, "an",
  231.         3, -1, "a",
  232.         3, -1, "w",
  233.         2,  2, "tel",
  234.         3, -1, "n",
  235.         3, -1, "t",
  236.         2,  2, "structure",
  237.         3, -1, "a",
  238.         3, -1, "b",
  239.         2,  0, "aux",
  240.         2,  1, "extra",
  241.         3, -1, "hot",
  242.         0,  0, 0
  243.     };
  244.     
  245.     c4_StructureMap map;
  246.     
  247.     for (c_Info* p = info; p->name; ++p)
  248.         if (p->count >= 0)
  249.             map.AddNode(p->level, p->name, 1, p->count, '=');
  250.         else
  251.             map.AddNode(p->level, p->name);
  252.             
  253.     puts(map.Result());
  254. }
  255.  
  256. /* Output should be:
  257.  
  258.  root 
  259.  ==== 
  260.   |  
  261.  1+- doc 
  262.      === 
  263.       |  
  264.      1+- naw 
  265.       |  === 
  266.       |   |  
  267.       |  1+- n 
  268.       |   |  == 
  269.       |   |   |  
  270.       |   |  1+- vn 
  271.       |   |   |      
  272.      2+---|---|- x 
  273.       |   |   |  
  274.       |   |  2+- an 
  275.       |   |          
  276.       |  2+- a 
  277.       |   |      
  278.       |  3+- w 
  279.       |          
  280.      3+- tel 
  281.       |  === 
  282.       |   |  
  283.       |  1+- n 
  284.       |   |      
  285.       |  2+- t 
  286.       |          
  287.      4+- structure 
  288.       |  ========= 
  289.       |   |  
  290.       |  1+- a 
  291.       |   |      
  292.       |  2+- b 
  293.       |          
  294.      5+- aux 
  295.       |  === 
  296.       |      
  297.      6+- extra 
  298.          ===== 
  299.           |  
  300.          1+- hot
  301. */
  302.  
  303. #endif
  304.  
  305. /////////////////////////////////////////////////////////////////////////////
  306.     
  307. /*! 960228: doesn't work, linker complains about mult-def, even with /NOE ???
  308.         // this stub prevents loading all handlers, which are not needed here
  309.     c4_Handler* f4_CreateHandler(char)
  310.     {
  311.         return 0;
  312.     }            
  313. */
  314.  
  315. int main(int argc, char** argv)
  316. {
  317.     #ifdef d4_InitMain
  318.         d4_InitMain(argc, argv);
  319.     #endif
  320.  
  321.     char option = 0;
  322.  
  323.         // check for a leading option and take it off   
  324.     if (argc > 1 && (*argv[1] == '-' || *argv[1] == '/'))
  325.     {
  326.         option = argv[1][1];
  327.         --argc;
  328.         ++argv;
  329.     }
  330.     
  331.         // the debug version tests CStructureMap if no filename is specified
  332.     if (argc != 2)
  333.     {
  334.         #ifdef _DEBUG
  335.             TestStructureMap();
  336.         #else
  337.             fputs("Usage: STRUCT [-d|-t|-c] datafile", stderr);
  338.         #endif
  339.         
  340.         return 1;
  341.     }
  342.  
  343.         // open the storage to obtain its structure definition
  344.     c4_Storage store (argv[1], false);
  345.     c4_Field& def = store.RootTable().Definition();
  346.  
  347.         // display the field structure in one of several formats
  348.     c4_String s;
  349.     switch (option)
  350.     {
  351.         case 'd': case 'D':     s = def.Description();          break;
  352.         case 't': case 'T':     s = def.Description(true);      break;
  353.         case 'c': case 'C':     s = DisplayTableStructure(def); break;
  354.         default:                s = DisplayFieldStructure(def);
  355.     }
  356.     puts(s);
  357.     
  358.     return 0;
  359. }
  360.  
  361. /////////////////////////////////////////////////////////////////////////////
  362. // $Id: struct.cpp,v 1.5 1996/12/06 23:39:31 jcw Exp $
  363.